/****************************************************************************************
**  File: Shader.hpp
**  Author: Asteroth
**  Date: 18/05/2013
****************************************************************************************/

#ifndef __ZEN_SHADER_HPP__
#define __ZEN_SHADER_HPP__

#include "../gl.hpp"

namespace zen {

	namespace video {

		class Shader {
		public:
			static const GLenum VERTEX_SHADER = GL_VERTEX_SHADER;
			static const GLenum GEOMETRY_SHADER = GL_GEOMETRY_SHADER;
			static const GLenum FRAGMENT_SHADER = GL_FRAGMENT_SHADER;

		private:
			friend class ShaderProgram;
			GLuint handle;
			GLenum type;
			bool compiled;

		public:
			Shader(const GLenum type): type(type) {
				compiled = false;
				handle = glCreateShader(this->type);
			}

			Shader(const GLenum type, const GLsizei rowCount, const char** code): type(type) {
				compiled = false;
				this->handle = glCreateShader(this->type);
				this->loadSource(rowCount, code);
			}

			Shader(const GLenum type, const std::string &fileName): type(type) {
				compiled = false;
				this->handle = glCreateShader(this->type);
				this->loadFile(fileName);
			}

			~Shader() {
				if (handle != 0)
					glDeleteShader(this->handle);
			}

			inline bool isCompiled()   {return this->compiled;}
			inline GLenum getType()      {return this->type;}

			inline bool loadSource(const GLsizei rowCount, const char** code) {
				if (this->handle != 0) {
					glShaderSource(this->handle, rowCount, code, NULL);
					glCompileShader(this->handle);
					GLint tmp;
					glGetShaderiv(this->handle, GL_COMPILE_STATUS, &tmp);
					this->compiled = tmp == GL_TRUE;
				}
				return this->compiled;
			}

			inline bool loadFile(const std::string &fileName) {
				this->compiled = false;
				if (!fileName.empty() && this->handle != 0) {
					zglShaderSource(this->handle, fileName, true);
					glCompileShader(this->handle);
					this->compiled = zglGetShaderCompileStatus(this->handle);
				}
				return this->compiled;
			}

			inline std::string getInfoLog() {
				char log[4094];
				GLsizei len;
				glGetShaderInfoLog(this->handle, 4094, &len, log);
				return std::string(log);
			}
		};

	} // namespace video

} // namespace zen

#endif // __ZEN_SHADER_HPP__
